import scala.util.parsing.combinator.syntactical._
import scala.collection.mutable._
import scala.collection.immutable.List
import layoutVariety.Box
import layoutVariety.Widget
import layoutVariety.MainWindow
import layoutVariety.WidgetFactory
import dataflowVariety.CustomAttribute
import dataflowVariety.Term
import dataflowVariety.Attribute
import layoutVariety.AlignDirection._;
import codegen._


package parser{


object comParser extends StandardTokenParsers 
{
	lexical.delimiters ++= List(";","+","-","=","(",")",":","\"","*","/","|","---","<-",",","[","]","?")
	lexical.reserved += ("label","textbox","button","checkbox","radiobutton","image","combobox","slider","high","width","x","tab","font","text","value","minvalue","maxvalue","fgcolor","bgcolor","halign","left","center","right","valign","top","middle","bottom")
	
	var boxes = HashMap[String,Box]() 
	
	var scope = HashMap[String,CustomAttribute]()
	
	private var virtualCusCount = 0
	
	private var root = new RootSyntaxNode()
	root.isRoot = true;
	private var generator = new CodeGenenrator(root,"generatedGui.scala")
	
	def genCode = generator.GenerateCode()
	
	def boxDef:Parser[Unit] = 
	{
	  ident ~ "<-" ~ verBox ^^	  {case s ~ "<-" ~ b => 	{	  
		  													//TODO: WTF ???
		  													//boxes(s)=b;
		  													println(s)
		  													var n = generator.createBox(s);		  													
		  													for (node <- b) 
		  													{
		  													  if(node.isBoxAddition) n.addDep(node) 
		  													  else n.addChild(node);
		  													}
		  													
		  													root.addChild(n);
		  												} 
	  							}	  
	}
	

	def box:Parser[List[SyntaxNode]] = 
	{
		(stdWidgetDefToBox|idnBox|surBoxWithAtt|surBoxWithSize|surBox)
	}	
	
	def horBox:Parser[List[SyntaxNode]] = 
	{
	   repsep(box, "|") ^^  { (ll: List[List[SyntaxNode]]) =>	{
		   															var k  = List[SyntaxNode]();
		   															k+:=generator.setAlignment("Hor");
		   															for (l <- ll) k:::=l;			  												
		   																
		   															var n = generator.createBox()
		   															for (node <- k) 
				  													{
				  													  if(node.isBoxAddition) n.addDep(node) 
				  													  else n.addChild(node);
				  													}
		   															root.addChild(n);
		   															List[SyntaxNode](generator.addBoxToBox(n.name));
	  															}
	  						}
	}
	
	def verBox:Parser[List[SyntaxNode]] = 
	{
	   repsep(horBox, "---") ^^  { (ll: List[List[SyntaxNode]]) =>	{
		   															var k  = List[SyntaxNode]();
		   															k+:=generator.setAlignment("Ver");	
		   															for (l <- ll) k:::=l;			  												
		   															
		   															var n = generator.createBox()
		   															for (node <- k) 
				  													{
				  													  if(node.isBoxAddition) n.addDep(node) 
				  													  else n.addChild(node);
				  													}
		   															root.addChild(n);
		   															List[SyntaxNode](generator.addBoxToBox(n.name));
	  															}
	  						}
	}
	
	def idnBox:Parser[List[SyntaxNode]] = 
	{
	  ident ^^ {case s =>
	    						{
	    						  println(s)
	    						  var l = List[SyntaxNode]()
	    						 var n = generator.addBoxToBox(s)
	    						 l:+n; 	    						  
	    						}
	    			}
	}
	
	
	def surBox:Parser[List[SyntaxNode]] = 
	{
		  "(" ~ verBox ~ ")"  ^^ {case  "(" ~ b ~ ")" => b}
	}
	
	def surBoxWithSize:Parser[List[SyntaxNode]] = 
	{
	  "(" ~ verBox ~ ")" ~ ":"  ~ size  ^^ 	{case "(" ~ s ~ ")"  ~ ":"  ~ b  =>	{
		  													s:::b;		  													
		  												}
	  						 	} 
	}
	
	def surBoxWithAtt:Parser[List[SyntaxNode]] = 
	{
	  "(" ~ verBox ~ ")"  ~ attBracket  ^^ 	{case "(" ~ s ~ ")"  ~ b =>	{
		  													s:::b;		  													
		  												}
	  						 	} 
	}
	
	def stdWidgetDefToBox:Parser[List[SyntaxNode]] = 
	{
		stdWidgetDef ^^ 	{case w => {
											var l = List[SyntaxNode]();
											l:+w											
										}
							}
		  					
	}
	def stdWidgetDef:Parser[SyntaxNode] = 
	{
	   "("~ stdWidgets ~":"~ size ~ ")" ~ attBracket ^^ {case"("~ w ~":"~ s ~ ")" ~ a =>	{
		   																						for(att <- a) w.addChild(att)
		   																						for(si<-s) w.addChild(si);
		   																						w;
	   																						} 
	   													}
	} 
	def stdWidgets:Parser[SyntaxNode] =  
	{
		("label"|"textbox"|"button"|"checkbox"|"radiobutton"|"image"|"combobox"|"slider"|"tab") ^^ 	{case s => 
		  																							{	
		  																							  println(s)
		  																								generator.addWidgetToBox(s);		  																							  
		  																							}		  																							
		  																						}
	}
	
	//TODO: check meaning of reserved
	def attribute:Parser[SyntaxNode] = 
	{
			textAttParser|integerParser|equationParser|initialize|colorParser|h_alignParser|v_alignParser|fontParser//|booleanParser 
	}
	
	def fontParser:Parser[SyntaxNode] = 
	{
	  ("font") ~ "=" ~ "("~ ident ~"," ~ ident ~ ","~ ident ~")" ^^ {case ("font") ~ "=" ~ "("~ s1~"," ~ s2 ~ ","~ s3 ~")" =>	{
		  																																		generator.setRealAttribute("font","("+ s1+"," + s2 + ","+ s3 +")")	    
	    																																	}
	  																			}
	}
	
	
	def textAttParser:Parser[SyntaxNode] =  
	{
	  	varTextAttParser|valTextAttParser
	}
	
	def varTextAttParser:Parser[SyntaxNode] =  
	{
	  (("text"|"image") ~ "=" ~ ident ) ^^ {					case (s ~ "=" ~ i ) => 	
	    																									{
	    																										generator.addCustomAttribute(s,i,false)
	  																										}
	    									}
	}
	
	def valTextAttParser:Parser[SyntaxNode] =  
	{
	  (("text"|"image") ~ "=" ~ stringLit) ^^ {					case (s ~ "=" ~ i ) => 	
	    																									{
	    																									  println(i)
	    																										generator.setRealAttribute(s,"\""+i+"\"")
	  																										}
	    									}
	}
	
	def integerParser:Parser[SyntaxNode] = 
	{
	  simpleNum | complexNum 
	}
	
	
	def simpleNum:Parser[SyntaxNode] =
	{
	  ("value"|"minvalue"|"maxvalue") ~ "=" ~ numericLit ^^ {case (a ~ "=" ~ n) =>	{
		  																				generator.setRealAttribute(a,n)
	  																				}
	  														}
	}
	  
	def complexNum:Parser[SyntaxNode] =
	{
	  ("value"|"minvalue"|"maxvalue") ~ "=" ~ term ^^ {case (a ~ "=" ~ t) =>	{
		  																			t.addVirtual(virtualCusCount)
		  																			virtualCusCount+=1
		  																			generator.setVirtualAttribute(t,a,true)
	  																			}
	  														}
	}
	
	def equationParser:Parser[SyntaxNode] =
	{
	  term ~ "=" ~ term ^^ 	{case t1 ~ "=" ~ t2 => 	{
		  												t1.negchain(t2)
		  												generator.addEquation(t1)
	  												}
	  						}
	}
	
	def colorParser:Parser[SyntaxNode] = 
	{
	  ("fgcolor"|"bgcolor") ~ "=" ~ ident ^^ {case (a ~ "=" ~ s) =>	{
  																			generator.setRealAttribute(a,s)
	  																	}
												}
	  
	}
	
	def h_alignParser:Parser[SyntaxNode] = 
	{
	  ("halign") ~ "=" ~ ("left"|"center"|"right") ^^	{case (a ~ "=" ~ s) =>	{
  																					generator.setRealAttribute(a,s)
	  																			}
														}
	  
	}
	
	def v_alignParser:Parser[SyntaxNode] = 
	{
	  ("valign") ~ "=" ~ ("top"|"middle"|"bottom") ^^	{case (a ~ "=" ~ s) =>	{
  																					generator.setRealAttribute(a,s)
	  																			}
														}
	  
	}
	
	
	def attBracket:Parser[List[SyntaxNode]] = 
	{
		"[" ~> repsep(attribute, ",") <~ "]" ^^ {  (al: List[SyntaxNode]) => al  }
	}
	
	def term:Parser[Term] = 
	{
		 factorTerm ~ opt(extensionTerm) ^^ {	case t2 ~ Some(t1) => {t2.chain(t1);t2}
		 										case t2 ~ None => {t2}}  
	}
	
	def extensionTerm:Parser[Term] = 
	{
		 ("+"|"-") ~ term ^^ {	case "+" ~ t1 => {t1}
		 						case "-" ~ t1 => {t1.setCoef(-1);t1}}  
	}	
	def factorTerm:Parser[Term] = 
	{
		mulTerm|divTerm    
	}
	
	def simpleTerm:Parser[Term] = 
	{
		numericalTerm|literalTerm|braceTerm  
	}
	
	def literalTerm:Parser[Term] = 
	{
	   ident ^^ {case s => {var t = new Term();t.addVar(s);println(s);t}} 
	}
	
	def mulTerm:Parser[Term] = 
	{
	 complexMulTerm|simpleTerm 
	}
	
	def complexMulTerm:Parser[Term] = 
	{
	   rep1sep(numericLit,"*") ~ opt(prefixSimpleTerm) ^^ {	case ln ~ Some(st) => {for (t<-ln) st.setCoef(t.toDouble);st}
	   														case ln ~ None=>{var t = new Term();	   																	
	   																		for (tmp<-ln) {var t1 = new Term();t1.setConst(tmp.toDouble);t.chain(t1)}
	   																		t} 
	   														}
	}
	
	def prefixSimpleTerm:Parser[Term] = 
	{
	  "*" ~ simpleTerm ^^ {case "*" ~ t => t}
	}
	
	def divTerm:Parser[Term] = 
	{
	    simpleTerm ~ "/" ~ numericLit  ^^ {case t1 ~ "/" ~ n => {t1.setCoef(1/n.toDouble);t1}} 
	}
	
	
	def numericalTerm:Parser[Term] = 
	{
	   numericLit ^^ {case s => {var t = new Term();t.setConst(s.toDouble);t}} 
	}	
		
	def braceTerm:Parser[Term] = 
	{
	   "("~>term<~ ")" ^^ {case t => t} 
	}
		
	def size:Parser[List[SyntaxNode]] = 
	{
	  w_basicSize ~ "x" ~ h_basicSize ^^ 	{case w~ "x" ~h => {
		  														var l = List[SyntaxNode]();
		  														l:+=w
		  														l:+h
	  														}
	    								}
	}
	
	def w_basicSize:Parser[SyntaxNode] = 
	{
	   w_numericSize | w_complexSize
	}
	
	def h_basicSize:Parser[SyntaxNode] = 
	{
	   h_numericSize | h_complexSize
	}
	
	def w_numericSize:Parser[SyntaxNode] = 
	{
	  numericLit ^^ {case n => {
		  							//TODO: for constraints monitoring
		  							//var a = new Attribute(Numeric,n.asInstanceOf[AnyRef]);a
		  							generator.setRealAttribute("width",n)	  							
	  							} 
	  				}
	}
	
	def h_numericSize:Parser[SyntaxNode] = 
	{
	  numericLit ^^ {case n => {
		  							//TODO: for constraints monitoring
		  							//var a = new Attribute(Numeric,n.asInstanceOf[AnyRef]);a
		  							generator.setRealAttribute("hight",n)		  							
	  							} 
	  				}
	}
	
	def w_complexSize:Parser[SyntaxNode] = 
	{
	  "(" ~> term <~ ")" ^^ {case t => {
			  								t.addVirtual(virtualCusCount);
			  								virtualCusCount+=1
		  									//var a =  new Attribute(CusNumeric,scope("virtual"+virtualCusCount.toString()).asInstanceOf[AnyRef]);
		  									//a
		  									generator.setVirtualAttribute(t,"width",true)
		  								}
	  						} 
	}
	
	def h_complexSize:Parser[SyntaxNode] = 
	{
	  "(" ~> term <~ ")" ^^ {case t => {
			  								t.addVirtual(virtualCusCount);
			  								virtualCusCount+=1
		  									//var a =  new Attribute(CusNumeric,scope("virtual"+virtualCusCount.toString()).asInstanceOf[AnyRef]);
		  									//a
		  									generator.setVirtualAttribute(t,"hight",true)
		  								}
	  						} 
	}
	
	def initialize:Parser[SyntaxNode] = 
	{
	  ident ~ "=" ~"?" ~ "(" ~ numericLit ~ ")" ^^ { case s ~ "=" ~"?" ~ "(" ~ n ~ ")" =>	{
		  																							println(s + n)
		  																							generator.assignToCustomAttribute(s,n.toDouble)
	    
	  																							} 
	    
	  													}
	}
	
	def initParser:Parser[Unit] = 
	{	  
	  rep(boxDef) ^^ {l:List[Unit] =>generator.GenerateCode()}	
	}
	
	def n:Parser[Unit] = 
	{
	  var ll:List[String] = null
	  repsep(numericLit,",") ^^ 
	  {l:List[String] =>{for (s<-l) println(s)}}
	}
}
}